#ifndef PICKER_H
#define PICKER_H


#include <map>
#include "GraphicsWindow.h"


class Picker{
    
private:  
	
	int lastPick;
	bool picking;
	GraphicsWindow* myParent;
    std::map<int, void (*)()> functions;
    
public:  
    
    void init(GraphicsWindow* gw)
    {
       myParent = gw;   
       lastPick = 0; 
	   picking = false;
    }
    
	bool isPicking() { return picking; }

    void load_object(int num)
    {
         glLoadName(num);
    }
    
    
    void load_object(int num, void (*func_p)())
    {
         glLoadName(num);
         functions[num] = func_p;
    }
    
    
    int get_object(int x, int y, int viewportOffset)
    { 
		picking = true;

        GLuint	buffer[512];
        GLint	hits;
    
        GLint	viewport[4];
        GLfloat projMat[16];

        glGetIntegerv(GL_VIEWPORT, viewport);
        glSelectBuffer(512, buffer);
        glRenderMode(GL_SELECT);

        glInitNames();
        glPushName(0);

        glMatrixMode(GL_PROJECTION);	
        glPushMatrix();
        /* get the current projection matrix */
        glGetFloatv (GL_PROJECTION_MATRIX, projMat);
        glLoadIdentity();

        // Create A Matrix That Will Zoom Up To A Small Portion Of The Screen
        gluPickMatrix((GLdouble) x, (GLdouble) ((viewport[3]-y)+viewportOffset), 2.0f, 2.0f, viewport);
        /* postmultiply the pick matrix with the current projection matrix */
        glMultMatrixf (projMat);
    
        glMatrixMode(GL_MODELVIEW);
        
        myParent->displayFunc();
        
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();	
        glMatrixMode(GL_MODELVIEW);
        glFlush();
        hits=glRenderMode(GL_RENDER);

        if (hits > 0)	
        {
		   int choose = buffer[3];
		   int depth = buffer[1];	

		   for (int loop = 1; loop < hits; loop++)
		   {
			   // if the object is closer than the one selected
			   if (buffer[loop*4+1] < GLuint(depth))
			   {
				  choose = buffer[loop*4+3];
				  depth = buffer[loop*4+1];
			   }
		    }
		    
		    if (functions.find(choose) != functions.end())
		    {
                functions[choose]();
            }
		    
			picking = false;
		    lastPick = choose;  
	        return choose;		
        }
        picking = false;
        return 0;
     }       
};


#endif  /* PICKER_H */
